<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <link href="../Styles/style.css" rel="stylesheet" type="text/css"/>


</head>

<body>
<div class="article-body">

    <div class="article-intro" id="content">

        <h1>Python3 多线程</h1>
        <p>多线程类似于同时执行多个不同程序，多线程运行有如下优点：</p>
        <ul>
            <li>使用线程可以把占据长时间的程序中的任务放到后台去处理。</li>
            <li>用户界面可以更加吸引人，这样比如用户点击了一个按钮去触发某些事件的处理，可以弹出一个进度条来显示处理的进度</li>
            <li>程序的运行速度可能加快</li>
            <li>在一些等待的任务实现上如用户输入、文件读写和网络收发数据等，线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。</li>
        </ul>
        <p>线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行，必须依存在应用程序中，由应用程序提供多个线程执行控制。
        </p>
        <p>每个线程都有他自己的一组CPU寄存器，称为线程的上下文，该上下文反映了线程上次运行该线程的CPU寄存器的状态。
        </p><p>指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器，线程总是在进程得到上下文中运行的，这些地址都用于标志拥有线程的进程地址空间中的内存。
    </p>
        <ul>

            <li>线程可以被抢占（中断）。</li>
            <li>在其他线程正在运行时，线程可以暂时搁置（也称为睡眠） -- 这就是线程的退让。
            </li>
        </ul>
        <p>线程可以分为:</p>

        <ul>
            <li><strong>内核线程：</strong>由操作系统内核创建和撤销。</li>
            <li><strong>用户线程：</strong>不需要内核支持而在用户程序中实现的线程。</li>
        </ul>

        <p>Python3 线程中常用的两个模块为：</p>
        <ul>
            <li><b>_thread</b></li>
            <li><b>threading(推荐使用)</b></li>
        </ul>
        <p> thread 模块已被废弃。用户可以使用 threading 模块代替。所以，在 Python3 中不能再使用"thread" 模块。为了兼容性，Python3 将 thread 重命名为 "_thread"。 </p>
        <br>
        <h2>开始学习Python线程</h2>
        <p>Python中使用线程有两种方式：函数或者用类来包装线程对象。</p>
        <p>函数式：调用 _thread 模块中的start_new_thread()函数来产生新线程。语法如下:</p>
        <pre class="prettyprint prettyprinted" style=""><span class="pln">_thread</span><span class="pun">.</span><span class="pln">start_new_thread </span><span class="pun">(</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">,</span><span class="pln"> args</span><span class="pun">[,</span><span class="pln"> kwargs</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span></pre>
        <p>参数说明:</p>
        <ul>
            <li>function - 线程函数。</li>
            <li>args - 传递给线程函数的参数,他必须是个tuple类型。</li>
            <li>kwargs - 可选参数。</li>
        </ul>
        <p>实例：</p>
        <pre class="prettyprint prettyprinted" style=""><span class="com">#!/usr/bin/python3</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> _thread
</span><span class="kwd">import</span><span class="pln"> time

</span><span class="com"># 为线程定义一个函数</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> print_time</span><span class="pun">(</span><span class="pln"> threadName</span><span class="pun">,</span><span class="pln"> delay</span><span class="pun">):</span><span class="pln">
   count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
   </span><span class="kwd">while</span><span class="pln"> count </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">:</span><span class="pln">
      time</span><span class="pun">.</span><span class="pln">sleep</span><span class="pun">(</span><span class="pln">delay</span><span class="pun">)</span><span class="pln">
      count </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
      </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"%s: %s"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> threadName</span><span class="pun">,</span><span class="pln"> time</span><span class="pun">.</span><span class="pln">ctime</span><span class="pun">(</span><span class="pln">time</span><span class="pun">.</span><span class="pln">time</span><span class="pun">())</span><span class="pln"> </span><span class="pun">))</span><span class="pln">

</span><span class="com"># 创建两个线程</span><span class="pln">
</span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
   _thread</span><span class="pun">.</span><span class="pln">start_new_thread</span><span class="pun">(</span><span class="pln"> print_time</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Thread-1"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
   _thread</span><span class="pun">.</span><span class="pln">start_new_thread</span><span class="pun">(</span><span class="pln"> print_time</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Thread-2"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="kwd">except</span><span class="pun">:</span><span class="pln">
   </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Error: 无法启动线程"</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
   </span><span class="kwd">pass</span></pre>
        <p>执行以上程序输出结果如下：</p>
        <pre class="prettyprint prettyprinted" style=""><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">36</span><span class="pun">:</span><span class="lit">31</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">36</span><span class="pun">:</span><span class="lit">33</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">36</span><span class="pun">:</span><span class="lit">33</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">36</span><span class="pun">:</span><span class="lit">35</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">36</span><span class="pun">:</span><span class="lit">37</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">36</span><span class="pun">:</span><span class="lit">37</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">36</span><span class="pun">:</span><span class="lit">39</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">36</span><span class="pun">:</span><span class="lit">41</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">36</span><span class="pun">:</span><span class="lit">45</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">36</span><span class="pun">:</span><span class="lit">49</span><span class="pln"> </span><span class="lit">2016</span></pre>
        <p>执行以上程后可以按下 ctrl-c to 退出。</p>


        <p>
        </p>
        <h2>线程模块</h2>
        <p>Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。</p><p>
        _thread 提供了低级别的、原始的线程以及一个简单的锁，它相比于 threading 模块的功能还是比较有限的。</p>
        <p>threading 模块除了包含 _thread 模块中的所有方法外，还提供的其他方法： </p>
        <ul>
            <li>threading.currentThread(): 返回当前的线程变量。 </li>
            <li>threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前，不包括启动前和终止后的线程。 </li>
            <li>threading.activeCount(): 返回正在运行的线程数量，与len(threading.enumerate())有相同的结果。</li>
        </ul>
        <p>除了使用方法外，线程模块同样提供了Thread类来处理线程，Thread类提供了以下方法:</p>
        <ul>
            <li><b>run():</b> 用以表示线程活动的方法。</li>
            <li><b>start():</b>启动线程活动。<p></p></li>
            <li><b> join([time]):</b> 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。</li>
            <li><b> isAlive():</b> 返回线程是否活动的。</li>
            <li><b> getName():</b> 返回线程名。</li>
            <li><b> setName():</b> 设置线程名。</li>
        </ul>

        <h2>使用 threading 模块创建线程</h2>
        <p>我们可以通过直接从 threading.Thread 继承创建一个新的子类，并实例化后调用 start() 方法启动新线程，即它调用了线程的 run()  方法：</p>
        <pre class="prettyprint prettyprinted" style=""><span class="com">#!/usr/bin/python3</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> threading
</span><span class="kwd">import</span><span class="pln"> time

exitFlag </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> myThread </span><span class="pun">(</span><span class="pln">threading</span><span class="pun">.</span><span class="typ">Thread</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> threadID</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> counter</span><span class="pun">):</span><span class="pln">
        threading</span><span class="pun">.</span><span class="typ">Thread</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">threadID </span><span class="pun">=</span><span class="pln"> threadID
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> counter
    </span><span class="kwd">def</span><span class="pln"> run</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"开始线程："</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln">
        print_time</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">counter</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"退出线程："</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> print_time</span><span class="pun">(</span><span class="pln">threadName</span><span class="pun">,</span><span class="pln"> delay</span><span class="pun">,</span><span class="pln"> counter</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">while</span><span class="pln"> counter</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> exitFlag</span><span class="pun">:</span><span class="pln">
            threadName</span><span class="pun">.</span><span class="kwd">exit</span><span class="pun">()</span><span class="pln">
        time</span><span class="pun">.</span><span class="pln">sleep</span><span class="pun">(</span><span class="pln">delay</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"%s: %s"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">threadName</span><span class="pun">,</span><span class="pln"> time</span><span class="pun">.</span><span class="pln">ctime</span><span class="pun">(</span><span class="pln">time</span><span class="pun">.</span><span class="pln">time</span><span class="pun">())))</span><span class="pln">
        counter </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

</span><span class="com"># 创建新线程</span><span class="pln">
thread1 </span><span class="pun">=</span><span class="pln"> myThread</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Thread-1"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
thread2 </span><span class="pun">=</span><span class="pln"> myThread</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Thread-2"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">

</span><span class="com"># 开启新线程</span><span class="pln">
thread1</span><span class="pun">.</span><span class="pln">start</span><span class="pun">()</span><span class="pln">
thread2</span><span class="pun">.</span><span class="pln">start</span><span class="pun">()</span><span class="pln">
thread1</span><span class="pun">.</span><span class="pln">join</span><span class="pun">()</span><span class="pln">
thread2</span><span class="pun">.</span><span class="pln">join</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"退出主线程"</span><span class="pun">)</span></pre>
        <p>以上程序执行结果如下；</p>
        <pre class="prettyprint prettyprinted" style=""><span class="pun">开始线程：</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pln">
</span><span class="pun">开始线程：</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">46</span><span class="pun">:</span><span class="lit">46</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">46</span><span class="pun">:</span><span class="lit">47</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">46</span><span class="pun">:</span><span class="lit">47</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">46</span><span class="pun">:</span><span class="lit">48</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">46</span><span class="pun">:</span><span class="lit">49</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">46</span><span class="pun">:</span><span class="lit">49</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">46</span><span class="pun">:</span><span class="lit">50</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="pun">退出线程：</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">46</span><span class="pun">:</span><span class="lit">51</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">46</span><span class="pun">:</span><span class="lit">53</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">46</span><span class="pun">:</span><span class="lit">55</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="pun">退出线程：</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pln">
</span><span class="pun">退出主线程</span></pre>

        <h2>线程同步</h2>
        <p>如果多个线程共同对某个数据修改，则可能出现不可预料的结果，为了保证数据的正确性，需要对多个线程进行同步。
        </p>
        <p>
            使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步，这两个对象都有 acquire 方法和 release 方法，对于那些需要每次只允许一个线程操作的数据，可以将其操作放到 acquire 和 release 方法之间。如下：
        </p>
        <p>多线程的优势在于可以同时运行多个任务（至少感觉起来是这样）。但是当线程需要共享数据时，可能存在数据不同步的问题。</p>
        <p>
            考虑这样一种情况：一个列表里所有元素都是0，线程"set"从后向前把所有元素改成1，而线程"print"负责从前往后读取列表并打印。</p>
        <p>
            那么，可能线程"set"开始改的时候，线程"print"便来打印列表了，输出就成了一半0一半1，这就是数据的不同步。为了避免这种情况，引入了锁的概念。
        </p>
        <p>
            锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时，必须先获得锁定；如果已经有别的线程比如"print"获得锁定了，那么就让线程"set"暂停，也就是同步阻塞；等到线程"print"访问完毕，释放锁以后，再让线程"set"继续。
        </p>
        <p>
            经过这样的处理，打印列表时要么全部输出0，要么全部输出1，不会再出现一半0一半1的尴尬场面。</p>
        <p>实例：</p>
        <pre class="prettyprint prettyprinted" style=""><span class="com">#!/usr/bin/python3</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> threading
</span><span class="kwd">import</span><span class="pln"> time

</span><span class="kwd">class</span><span class="pln"> myThread </span><span class="pun">(</span><span class="pln">threading</span><span class="pun">.</span><span class="typ">Thread</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> threadID</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> counter</span><span class="pun">):</span><span class="pln">
        threading</span><span class="pun">.</span><span class="typ">Thread</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">threadID </span><span class="pun">=</span><span class="pln"> threadID
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">counter </span><span class="pun">=</span><span class="pln"> counter
    </span><span class="kwd">def</span><span class="pln"> run</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"开启线程： "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln">
        </span><span class="com"># 获取锁，用于线程同步</span><span class="pln">
        threadLock</span><span class="pun">.</span><span class="pln">acquire</span><span class="pun">()</span><span class="pln">
        print_time</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">counter</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln">
        </span><span class="com"># 释放锁，开启下一个线程</span><span class="pln">
        threadLock</span><span class="pun">.</span><span class="pln">release</span><span class="pun">()</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> print_time</span><span class="pun">(</span><span class="pln">threadName</span><span class="pun">,</span><span class="pln"> delay</span><span class="pun">,</span><span class="pln"> counter</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">while</span><span class="pln"> counter</span><span class="pun">:</span><span class="pln">
        time</span><span class="pun">.</span><span class="pln">sleep</span><span class="pun">(</span><span class="pln">delay</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"%s: %s"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">threadName</span><span class="pun">,</span><span class="pln"> time</span><span class="pun">.</span><span class="pln">ctime</span><span class="pun">(</span><span class="pln">time</span><span class="pun">.</span><span class="pln">time</span><span class="pun">())))</span><span class="pln">
        counter </span><span class="pun">-=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

threadLock </span><span class="pun">=</span><span class="pln"> threading</span><span class="pun">.</span><span class="typ">Lock</span><span class="pun">()</span><span class="pln">
threads </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">

</span><span class="com"># 创建新线程</span><span class="pln">
thread1 </span><span class="pun">=</span><span class="pln"> myThread</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Thread-1"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
thread2 </span><span class="pun">=</span><span class="pln"> myThread</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Thread-2"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">

</span><span class="com"># 开启新线程</span><span class="pln">
thread1</span><span class="pun">.</span><span class="pln">start</span><span class="pun">()</span><span class="pln">
thread2</span><span class="pun">.</span><span class="pln">start</span><span class="pun">()</span><span class="pln">

</span><span class="com"># 添加线程到线程列表</span><span class="pln">
threads</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">thread1</span><span class="pun">)</span><span class="pln">
threads</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">thread2</span><span class="pun">)</span><span class="pln">

</span><span class="com"># 等待所有线程完成</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> t </span><span class="kwd">in</span><span class="pln"> threads</span><span class="pun">:</span><span class="pln">
    t</span><span class="pun">.</span><span class="pln">join</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"退出主线程"</span><span class="pun">)</span></pre>
        <p>执行以上程序，输出结果为：</p>
        <pre class="prettyprint prettyprinted" style=""><span class="pun">开启线程：</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pln">
</span><span class="pun">开启线程：</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">52</span><span class="pun">:</span><span class="lit">57</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">52</span><span class="pun">:</span><span class="lit">58</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">52</span><span class="pun">:</span><span class="lit">59</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">53</span><span class="pun">:</span><span class="lit">01</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">53</span><span class="pun">:</span><span class="lit">03</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Apr</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">53</span><span class="pun">:</span><span class="lit">05</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">
</span><span class="pun">退出主线程</span></pre>

        <h2>线程优先级队列（ Queue）
        </h2>
        <p>Python 的 Queue 模块中提供了同步的、线程安全的队列类，包括FIFO（先入先出)队列Queue，LIFO（后入先出）队列LifoQueue，和优先级队列 PriorityQueue。
        </p><p>这些队列都实现了锁原语，能够在多线程中直接使用，可以使用队列来实现线程间的同步。</p>

        <p>Queue 模块中的常用方法:</p><p>
    </p><ul>
        <li>Queue.qsize() 返回队列的大小 </li>
        <li>Queue.empty() 如果队列为空，返回True,反之False </li>
        <li>Queue.full() 如果队列满了，返回True,反之False</li>
        <li>Queue.full 与 maxsize 大小对应 </li>
        <li>Queue.get([block[, timeout]])获取队列，timeout等待时间 </li>
        <li>Queue.get_nowait() 相当Queue.get(False)</li>
        <li>Queue.put(item) 写入队列，timeout等待时间 </li>
        <li>Queue.put_nowait(item) 相当Queue.put(item, False)</li>
        <li>Queue.task_done() 在完成一项工作之后，Queue.task_done()函数向任务已经完成的队列发送一个信号</li>
        <li>Queue.join() 实际上意味着等到队列为空，再执行别的操作</li>
    </ul>
        <p>实例:</p>
        <pre class="prettyprint prettyprinted" style=""><span class="com">#!/usr/bin/python3</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> queue
</span><span class="kwd">import</span><span class="pln"> threading
</span><span class="kwd">import</span><span class="pln"> time

exitFlag </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> myThread </span><span class="pun">(</span><span class="pln">threading</span><span class="pun">.</span><span class="typ">Thread</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> threadID</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> q</span><span class="pun">):</span><span class="pln">
        threading</span><span class="pun">.</span><span class="typ">Thread</span><span class="pun">.</span><span class="pln">__init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">threadID </span><span class="pun">=</span><span class="pln"> threadID
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">q </span><span class="pun">=</span><span class="pln"> q
    </span><span class="kwd">def</span><span class="pln"> run</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"开启线程："</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln">
        process_data</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">q</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"退出线程："</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> process_data</span><span class="pun">(</span><span class="pln">threadName</span><span class="pun">,</span><span class="pln"> q</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">while</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> exitFlag</span><span class="pun">:</span><span class="pln">
        queueLock</span><span class="pun">.</span><span class="pln">acquire</span><span class="pun">()</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> workQueue</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">():</span><span class="pln">
            data </span><span class="pun">=</span><span class="pln"> q</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">()</span><span class="pln">
            queueLock</span><span class="pun">.</span><span class="pln">release</span><span class="pun">()</span><span class="pln">
            </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"%s processing %s"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">threadName</span><span class="pun">,</span><span class="pln"> data</span><span class="pun">))</span><span class="pln">
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            queueLock</span><span class="pun">.</span><span class="pln">release</span><span class="pun">()</span><span class="pln">
        time</span><span class="pun">.</span><span class="pln">sleep</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln">

threadList </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">"Thread-1"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Thread-2"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Thread-3"</span><span class="pun">]</span><span class="pln">
nameList </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">"One"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Two"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Three"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Four"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Five"</span><span class="pun">]</span><span class="pln">
queueLock </span><span class="pun">=</span><span class="pln"> threading</span><span class="pun">.</span><span class="typ">Lock</span><span class="pun">()</span><span class="pln">
workQueue </span><span class="pun">=</span><span class="pln"> queue</span><span class="pun">.</span><span class="typ">Queue</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln">
threads </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
threadID </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

</span><span class="com"># 创建新线程</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> tName </span><span class="kwd">in</span><span class="pln"> threadList</span><span class="pun">:</span><span class="pln">
    thread </span><span class="pun">=</span><span class="pln"> myThread</span><span class="pun">(</span><span class="pln">threadID</span><span class="pun">,</span><span class="pln"> tName</span><span class="pun">,</span><span class="pln"> workQueue</span><span class="pun">)</span><span class="pln">
    thread</span><span class="pun">.</span><span class="pln">start</span><span class="pun">()</span><span class="pln">
    threads</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">thread</span><span class="pun">)</span><span class="pln">
    threadID </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

</span><span class="com"># 填充队列</span><span class="pln">
queueLock</span><span class="pun">.</span><span class="pln">acquire</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> word </span><span class="kwd">in</span><span class="pln"> nameList</span><span class="pun">:</span><span class="pln">
    workQueue</span><span class="pun">.</span><span class="pln">put</span><span class="pun">(</span><span class="pln">word</span><span class="pun">)</span><span class="pln">
queueLock</span><span class="pun">.</span><span class="pln">release</span><span class="pun">()</span><span class="pln">

</span><span class="com"># 等待队列清空</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> workQueue</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">pass</span><span class="pln">

</span><span class="com"># 通知线程是时候退出</span><span class="pln">
exitFlag </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

</span><span class="com"># 等待所有线程完成</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> t </span><span class="kwd">in</span><span class="pln"> threads</span><span class="pun">:</span><span class="pln">
    t</span><span class="pun">.</span><span class="pln">join</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"退出主线程"</span><span class="pun">)</span></pre>
        <p>以上程序执行结果：</p>

        <pre class="prettyprint prettyprinted" style=""><span class="pun">开启线程：</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pln">
</span><span class="pun">开启线程：</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pln">
</span><span class="pun">开启线程：</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">3</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">3</span><span class="pln"> processing </span><span class="typ">One</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pln"> processing </span><span class="typ">Two</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pln"> processing </span><span class="typ">Three</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">3</span><span class="pln"> processing </span><span class="typ">Four</span><span class="pln">
</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pln"> processing </span><span class="typ">Five</span><span class="pln">
</span><span class="pun">退出线程：</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">3</span><span class="pln">
</span><span class="pun">退出线程：</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">2</span><span class="pln">
</span><span class="pun">退出线程：</span><span class="typ">Thread</span><span class="pun">-</span><span class="lit">1</span><span class="pln">
</span><span class="pun">退出主线程</span></pre>

    </div>
</div>
</body>
</html>
